Skip to content

Animate navigation bar visibility - #414

Merged
marcprux merged 2 commits into
skiptools:mainfrom
dfabulich:animate-nav-bar
May 14, 2026
Merged

Animate navigation bar visibility#414
marcprux merged 2 commits into
skiptools:mainfrom
dfabulich:animate-nav-bar

Conversation

@dfabulich

@dfabulich dfabulich commented May 7, 2026

Copy link
Copy Markdown
Member

There are three kinds of changes here.

  1. We have to plumb the visibilityAnimation through a preference so Navigation.swift can access it.
  2. Adding in AnimatedVisibility. (This changes indentation on the whole file. Best viewed ignoring whitespace, e.g. with git diff -w)
  3. Careful coordination of contentSafeArea with topPadding. These need to match each other on every frame of the animation, or the animation will judder.

Videos

Videos

Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-05-07.at.16.41.04.mov
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-05-07.at.16.42.00.mov
Screen_recording_20260507_164120.webm
Screen_recording_20260507_164143.webm

Skip Pull Request Checklist:

  • REQUIRED: I have signed the Contributor Agreement
  • REQUIRED: I have tested my change locally with swift test
  • OPTIONAL: I have tested my change on an iOS simulator or device
  • OPTIONAL: I have tested my change on an Android emulator or device
  • REQUIRED: I have checked whether this change requires a corresponding update in the Skip Fuse UI repository (link related PR if applicable)
    None required
  • OPTIONAL: I have added an example of any UI changes in the Showcase sample app
    Example of animating navigation bar visibility skipapp-showcase#97

  • AI was used to generate or assist with generating this PR. Please specify below how you used AI to help you, and what steps you have taken to manually verify the changes.

Cursor added in AnimatedVisibility; I wrote the code to coordinate contentSafeArea and topPadding, and tested it in Showcase Lite, in skiptools/skipapp-showcase#97 in both the "Geometry Padding" and "Geometry padding in sheet" playgrounds.

There are three kinds of changes here.

1. We have to plumb the `visibilityAnimation` through a preference so `Navigation.swift` can access it.
2. Adding in `AnimatedVisibility`. (This changes indentation on the whole file. Best viewed ignoring whitespace, e.g. with `git diff -w`)
3. Careful coordination of `contentSafeArea` with `topPadding`. These need to match each other on every frame of the animation, or the animation will judder.
@cla-bot cla-bot Bot added the cla-signed label May 7, 2026
@dfabulich

Copy link
Copy Markdown
Member Author

I tried also adding animation support for the tab bar and the "bottom bar" toolbar, but it turned out to be a lot harder than just animating the top bar. I may pick it up again some day.

For future work: I suspect that we no longer need to separately track topBarBottomPx and topBarHeightPx. But this code is very hard to work with, and requires a lot of careful testing and scrutinizing logs, so I'm not attempting to do that now.

@dfabulich

Copy link
Copy Markdown
Member Author

Updated with videos

@marcprux

Copy link
Copy Markdown
Member

Very nice improvement, thanks!

@marcprux
marcprux merged commit 624f900 into skiptools:main May 14, 2026
2 checks passed
@dfabulich dfabulich mentioned this pull request May 15, 2026
7 tasks
vincentborko added a commit to vincentborko/skip-ui that referenced this pull request Jun 1, 2026
skiptools#414 (Animate navigation bar visibility) moved the "reset top-bar inset to
0 when hidden" into a DisposableEffect.onDispose *inside*
AnimatedVisibility(visible: showTopBar). AnimatedVisibility with visible=false
never composes its content, so for a title-less root (showTopBar == false from
the start) that onDispose never runs — leaving topBarBottomPx at its initial
safeArea + 112dp and pushing content down by a phantom top inset.

Initialize the inset to 0 when showTopBar is false, and add a
LaunchedEffect(showTopBar) that clears it on any visible→hidden transition.
The 112dp anti-flash init is preserved for bars that are actually shown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
marcprux pushed a commit that referenced this pull request Jun 1, 2026
#452)

#414 (Animate navigation bar visibility) moved the "reset top-bar inset to
0 when hidden" into a DisposableEffect.onDispose *inside*
AnimatedVisibility(visible: showTopBar). AnimatedVisibility with visible=false
never composes its content, so for a title-less root (showTopBar == false from
the start) that onDispose never runs — leaving topBarBottomPx at its initial
safeArea + 112dp and pushing content down by a phantom top inset.

Initialize the inset to 0 when showTopBar is false, and add a
LaunchedEffect(showTopBar) that clears it on any visible→hidden transition.
The 112dp anti-flash init is preserved for bars that are actually shown.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants